package com.envper.common.service.device.impl;

import com.envper.common.domain.alarm.AlarmType;
import com.envper.common.domain.device.Payload;
import com.envper.common.domain.dto.DeviceThresholdDto;
import com.envper.common.exception.GlobalException;
import com.envper.common.mapper.DeviceMapper;
import com.envper.common.service.alarm.AlarmService;
import com.envper.common.service.device.DeviceThresholdService;
import com.envper.common.util.IdUtils;
import com.envper.mysql.base.service.DeviceThresholdBaseService;
import com.envper.mysql.domain.Status;
import com.envper.mysql.domain.entity.TDeviceThreshold;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
public class DeviceThresholdServiceImpl implements DeviceThresholdService {
    private final DeviceThresholdBaseService deviceThresholdBaseService;
    private final AlarmService alarmService;

    @Override
    public List<DeviceThresholdDto> getDeviceThresholdList() {
        List<TDeviceThreshold> tDeviceThresholds = deviceThresholdBaseService.list();
        return DeviceMapper.INSTANCE.toDeviceThresholdDtoList(tDeviceThresholds);
    }

    @Override
    public void createDeviceThreshold(DeviceThresholdDto deviceThresholdDto) {
        TDeviceThreshold tDeviceThreshold = DeviceMapper.INSTANCE.toTDeviceThreshold(deviceThresholdDto);
        tDeviceThreshold.setId(IdUtils.createId());
        tDeviceThreshold.setCreated(LocalDateTime.now());
        tDeviceThreshold.setUpdated(LocalDateTime.now());
        boolean save = deviceThresholdBaseService.save(tDeviceThreshold);
        if (!save) throw new GlobalException(Status.CREATEERROR);
    }

    @Override
    public void checkDeviceThreshold(Payload payload) {
        if (ObjectUtils.isEmpty(payload.getDeviceId())) return;
        boolean exists = deviceThresholdBaseService.exists(new QueryWrapper().eq("device_id", payload.getDeviceId()));
        if (!exists) return;
        TDeviceThreshold tDeviceThreshold = deviceThresholdBaseService.getOne(new QueryWrapper().eq("device_id", payload.getDeviceId()));
        if (ObjectUtils.isEmpty(tDeviceThreshold)) return;
        Float temperature = payload.getTemperature();
        Float humidity = payload.getHumidity();
        if (ObjectUtils.isEmpty(temperature) || ObjectUtils.isEmpty(humidity)) return;
        if (temperature < tDeviceThreshold.getTemperatureLower()) {
            alarmService.triggerAlarm(payload.getDeviceId(), AlarmType.TemperatureToLow);
        } else if (temperature > tDeviceThreshold.getTemperatureUpper()) {
            alarmService.triggerAlarm(payload.getDeviceId(), AlarmType.TemperatureToHigh);
        } else if (humidity < tDeviceThreshold.getHumidityLower()) {
            alarmService.triggerAlarm(payload.getDeviceId(), AlarmType.HumidityToLow);
        } else if (humidity > tDeviceThreshold.getHumidityUpper()) {
            alarmService.triggerAlarm(payload.getDeviceId(), AlarmType.HumidityToHigh);
        }
    }

    @Override
    public void deleteDeviceThreshold(Long id) {
        boolean removed = deviceThresholdBaseService.removeById(id);
        if (!removed) throw new GlobalException(Status.DELETEERROR);
    }

    @Override
    public void editDeviceThreshold(DeviceThresholdDto deviceThresholdDto) {
        TDeviceThreshold tDeviceThreshold = DeviceMapper.INSTANCE.toTDeviceThreshold(deviceThresholdDto);
        boolean removed = deviceThresholdBaseService.updateById(tDeviceThreshold);
        if (!removed) throw new GlobalException(Status.UPDATEERROR);
    }
}
